package com.hframe;


import com.hframe.data.DRef;
import com.hframe.database.DatabasePool;
import com.hframe.filter.PageSkipFilter;
import com.hframe.filter.UrlRewrite;
import com.hframe.log.InitLog;
import com.hframe.thread.ThreadPool;
import org.apache.log4j.Logger;

import javax.servlet.*;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Map;

/**
 * 初始化框架
 * 在web.xml文件加添加
 */
public class FrameInit implements ServletContextListener {
    public static final String SkipFilterName = "SkipFilterName";
    public static final String UrlRewriteName = "UrlRewriteName";

    protected static final ArrayList<String> servletUrls = new ArrayList<>();
    static Logger log = Logger.getLogger(FrameInit.class);
    private InitLog initLog = new InitLog();
    protected ServletContext servletContext = null;

    public InitLog getLog() {
        return initLog;
    }

    public void setLog(InitLog log) {
        this.initLog = log;
    }

    /**
     * 销毁
     *
     * @param event
     */
    @Override
    public void contextDestroyed(ServletContextEvent event) {
        destroyed(event.getServletContext());
        ThreadPool.shutdown();
        servletUrls.clear();
        DatabasePool.shutdown();
        log.info("Framework have withdrawn from the  (框架已退出)");
    }

    /**
     * 初始化
     *
     * @param event
     */
    @Override
    public void contextInitialized(ServletContextEvent event) {
        servletContext = event.getServletContext();
        readConfig(servletContext);

        initialized(servletContext);
        initServletUrls(servletContext);

        log.info("Framework to complete initialization  (框架完成初始化)");
    }

    /**
     * 读取配置文件监听
     * 初始化参数(initParam)
     * 参数名 ConfigClass
     * 参数值 用于保存配置的对像。需要有静态 get 方法的工厂方法
     */
    protected void readConfig(ServletContext context) {
        String ConfigClass = context.getInitParameter("ConfigClass");
        if (null != ConfigClass) {
            try {
                Class<?> className = Class.forName(ConfigClass);
                Method get = className.getDeclaredMethod("get");

                new ReadConfig(context).readConfig((DRef<? extends DRef<?>>) get.invoke(null));
            } catch (Exception e) {
                log.error(e.toString(), e);
            }
        }
    }

    private void initServletUrls(ServletContext servletContext) {
        servletUrls.clear();
        Map<String, ? extends ServletRegistration> map = servletContext.getServletRegistrations();
        for (Map.Entry<String, ? extends ServletRegistration> eny : map.entrySet()) {
            Collection<String> coll = eny.getValue().getMappings();
            Object[] path = coll.toArray();
            for (int i = 0; i < path.length; i++) {
                servletUrls.add(path[i].toString());
            }
        }
    }

    public static ArrayList<String> getServleturls() {
        return servletUrls;
    }

    protected void initialized(ServletContext servletContext) {
        if (null != initLog)
            initLog.initialized(servletContext);
        initFilter(servletContext);
    }

    protected void destroyed(ServletContext servletContext) {
        if (null != initLog)
            initLog.destroyed(servletContext);
    }

    protected void initFilter(ServletContext context) {
        FilterRegistration.Dynamic dyn = this.servletContext.addFilter("SetCharacterEncoding", org.apache.catalina.filters.SetCharacterEncodingFilter.class);
        dyn.setInitParameter("encoding", "UTF-8");
        dyn.addMappingForUrlPatterns(null, true, "/*");

        dyn = this.servletContext.addFilter("CSRF", org.apache.catalina.filters.SetCharacterEncodingFilter.class);
        dyn.setInitParameter("entryPoints", "/html,/html/,/html/list,/index.jsp");
        dyn.addMappingForServletNames(null, true, "HTMLHostManager");

        //添加伪静态页面转换过滤器
        String pattern = context.getInitParameter("UrlRewritePattern");
        if (null != pattern && UrlRewrite.init(context)) {
            dyn = this.servletContext.addFilter(UrlRewriteName, UrlRewrite.class);
            dyn.addMappingForUrlPatterns(null, true, 0 < pattern.trim().length() ? "/*" : pattern.trim());
        }

        //添加页面中转过滤器
        dyn = this.servletContext.addFilter(SkipFilterName, PageSkipFilter.class);
        String pageSkipType = context.getInitParameter("PageSkipType");

        EnumSet<DispatcherType> enumset = EnumSet.noneOf(DispatcherType.class);
        enumset.add(DispatcherType.FORWARD);
        enumset.add(DispatcherType.INCLUDE);
        enumset.add(DispatcherType.REQUEST);

        if (null == pageSkipType) {
            dyn.addMappingForUrlPatterns(enumset, true, "*.jsp");
        } else {
            for (String item : pageSkipType.split(",")) {
                dyn.addMappingForUrlPatterns(enumset, true, item);
            }
        }

    }

}
